/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.cicp.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import com.sinodata.bsm.cicp.Startup;
import com.sinodata.bsm.cicp.task.TaskManager;
import com.sinodata.bsm.cicp.util.SystemContext;
import com.sinodata.bsm.cicp.util.pool.SSH2ConnPool;
import com.sinodata.bsm.cicp.util.pool.TelnetConnPool;
import com.sinodata.bsm.cicp.util.telnet.EthzSSH;
import com.sinodata.bsm.cicp.util.telnet.JtaTelnet;
import com.sinodata.bsm.cicp.util.telnet.PromptFilter;
import com.sinodata.bsm.common.constants.SystemStatus;

/**
 * <p> 
 * Description: 
 * </p>
 *
 * @author tangli
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-8-20 下午3:49:52          tangli         1.0         To create
 * </p>
 *
 * @since    
 * @see     
 */
public class SystemService {

    private static Logger logger = Logger.getLogger(SystemService.class);

    private final static int DEFAULT_TIMEOUT = 60 * 1000;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 
     */
    public SystemService() {

    }

    /**
     * 获取probe的状态
     * @return
     */
    public String[] getProbeStatus() {
        int taskSize = TaskManager.getInstance().getFixTaskCount();
        String[] result = { "" + taskSize };
        return result;
    }

    /**
     * 让probe重启
     * @return
     */
    public String stopProbe() {
        Startup.next(SystemStatus.STATUS_RESTART);
        logger.info("接到重启命令  开始重启...");
        return "";
    }

    /**
     * 获取当前时间
     * @return
     */
    public String getCurrenTime() {
        return sdf.format(new Date());
    }

    /**
     * 获取一个probe中的资源总数
     * @return
     */
    public String getResCount() {

        return "";
    }

    /**
     * 查看quartz任务数
     * @return
     */
    public String[] getProbeTask() {
        StringBuffer bufStr = new StringBuffer();
        String[] stry = new String[4];
        stry[0] = (String) SystemContext.getProperty("quatrz.thread");
        stry[1] = TaskManager.getInstance().getFixTaskCount() + "";
        try {
            List<JobExecutionContext> jobs = TaskManager.getInstance().getCurrentlyExecutingJobs();
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (int i = 0; i < jobs.size(); i++) {
                JobExecutionContext context = jobs.get(i);
                JobDataMap dataMap = context.getJobDetail().getJobDataMap();
                Long resId = dataMap.getLong("JOB_KEY_RESID");
                Long collTaskId = dataMap.getLong("JOB_KEY_TASKID");
                long begin = dataMap.getLong("begin");
                long curr = new Date().getTime();
                bufStr.append(resId);
                bufStr.append("#").append(collTaskId);
                bufStr.append("#").append(formatter.format(new Date(begin)));
                bufStr.append("#").append((curr - begin) / (1000d));
                bufStr.append(",");
            }
            stry[2] = jobs.size() + "";
            stry[3] = bufStr.toString();
        } catch (Exception e) {
            logger.error(e);
        }
        return stry;
    }

    /**
     * 获取虚拟机信息
     * @return
     */
    public String[] getJvmInfo() {
        String[] stry = new String[6];
        stry[0] = Runtime.getRuntime().maxMemory() / (1024 * 1024) + "";
        stry[1] = Runtime.getRuntime().totalMemory() / (1024 * 1024) + "";
        stry[2] = Runtime.getRuntime().freeMemory() / (1024 * 1024) + "";
        stry[3] = System.getProperty("java.version");
        stry[4] = System.getProperty("java.vendor");
        stry[5] = TrapReceiverDeamon.TRAP_SERVICE_STATUS;
        return stry;
    }

    /**
     * 通过ssh2执行一个命令
     * @param ip
     * @param pwd
     * @param cmd
     * @param pool   是否使用连接池    false:不使用    使用：使用
     * @return
     */
    public String execSSH2(String ip, String port, String user, String auth, String file, String pwd, String cmd, String pool) {
        String retVal = "";
        EthzSSH ssh2 = null;
        Session session = null;
        Connection conn = null;
        BufferedReader br = null;
        BufferedReader be = null;
        logger.info("[TIP]\t ssh2 " + ip + "_" + cmd);
        try {
            if ("false".equals(pool)) {
                ssh2 = new EthzSSH();
                ssh2.login(ip, Integer.parseInt(port), user, auth, pwd, file);
                ssh2.setValid(true);
            } else {
                ssh2 = SSH2ConnPool.getInstance().getConnection(ip, Integer.parseInt(port), user, pwd, 3);
            }
            conn = ssh2.getConn();
            session = conn.openSession();
            session.execCommand(cmd);
            StringBuilder sb = new StringBuilder();
            String tmpStr = "";
            //获取标准错误
            InputStream stderr = new StreamGobbler(session.getStderr());
            be = new BufferedReader(new InputStreamReader(stderr, "GBK"));
            while ((tmpStr = be.readLine()) != null) {
                sb.append(tmpStr + "\n");
            }
            //获取标准输出
            InputStream stdout = new StreamGobbler(session.getStdout());
            br = new BufferedReader(new InputStreamReader(stdout, "GBK"));
            while ((tmpStr = br.readLine()) != null) {
                sb.append(tmpStr + "\n");
            }
            retVal = sb.toString();
        } catch (Throwable t) {
            if (ssh2 != null) {
                ssh2.setValid(false);
            }
            t.printStackTrace();
            retVal = t.toString();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                }
            }
            if (be != null) {
                try {
                    be.close();
                } catch (Exception e) {
                }
            }
            try {
                //session在每次执行命令后都要关闭
                if (session != null) {
                    session.close();
                }
                if (ssh2 != null) {
                    if ("false".equals(pool)) {
                        ssh2.disconn();
                    } else {
                        SSH2ConnPool.getInstance().free(ip, ssh2);
                    }
                }
            } catch (Exception e) {
                logger.error("Failed when free a ssh2Connection", e);
            }
        }
        return retVal;
    }

    @SuppressWarnings("unchecked")
    public String snmpConn(String ip, String port, String community, String version, String oid) {
        Snmp snmp = null;
        logger.info("[TIP]\t snmpConn " + ip + "_" + version + "_" + oid);
        try {
            StringBuilder sb = new StringBuilder();
            DefaultUdpTransportMapping udpTransportMap = null;
            Address targetAddress = GenericAddress.parse(ip.trim() + "/" + port);
            CommunityTarget target = new CommunityTarget();
            target.setCommunity(new OctetString(community));
            target.setVersion(1);
            target.setAddress(targetAddress);
            target.setRetries(3);
            target.setTimeout(3000);

            udpTransportMap = new DefaultUdpTransportMapping();
            snmp = new Snmp(udpTransportMap);
            snmp.listen();
            PDU request = new PDU();
            request.setType(PDU.GET);
            request.add(new VariableBinding(new OID(oid)));
            PDU response = null;
            ResponseEvent responseEvent = snmp.send(request, target);
            response = responseEvent.getResponse();
            if (response != null) {
                if (response.getErrorIndex() == PDU.noError && response.getErrorStatus() == PDU.noError) {
                    Vector<VariableBinding> recVBs = response.getVariableBindings();
                    for (int i = 0; i < recVBs.size(); i++) {
                        VariableBinding recVB = recVBs.elementAt(i);
                        sb.append(recVB.getVariable().toString() + " \n");
                    }
                }
            }
            logger.info(sb.toString());
            return sb.toString();
        } catch (Exception e) {
            logger.error(e);
        } finally {
            if (snmp != null) {
                try {
                    snmp.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
        return "null";
    }

    /**
     * 通过Telnet执行测试命令
     * @param ip
     * @param port
     * @param user
     * @param auth
     * @param file
     * @param pwd
     * @param cmd
     * @param pool
     * @return
     */
    public String execTelnet(String ip, String port, String user, String pwd, String cmd, String pool, String prompt) {
        String retVal = "";
        JtaTelnet telnet = null;
        Session session = null;
        BufferedReader br = null;
        BufferedReader be = null;

        logger.info(ip + "-->" + user + "-->" + port + "-->" + pwd + "-->" + cmd + "-->" + pool + "-->" + prompt);

        try {
            if ("false".equals(pool)) {
                telnet = new JtaTelnet();
                telnet.connect(ip, Integer.parseInt(port));
                telnet.runLogin(user, pwd, prompt);
                telnet.setIsValid(true);
                /**
                 * 采集命令应在bash下执行
                 */
                telnet.runTask("bash");
                /**
                 * 改为英语环境 否则解析shell时会混乱
                 */
                telnet.runTask("export LANG=C;");
            } else {
                telnet = TelnetConnPool.getInstance().getTelnet(ip, Integer.parseInt(port), user, pwd, 2, prompt);
            }

            String shellOut = telnet.runTask(cmd);

            //对返回内容先做一下处理
            /**
             * 去掉命令行
             */
            shellOut = PromptFilter.trimCommandPrompt(shellOut, cmd, prompt);

            /**
             * 过滤掉null字符
             */
            byte b0[] = { 0x00 };
            shellOut = shellOut.replaceAll(new String(b0), "");

            StringBuffer strBuff = new StringBuffer();
            strBuff.append(shellOut);
            StringReader strReader = new StringReader(strBuff.toString());
            BufferedReader buffReader = new BufferedReader(strReader);
            String strLine = null;
            StringBuilder sb = new StringBuilder();
            while ((strLine = buffReader.readLine()) != null) {
                sb.append(strLine + "\n");
            }
            return sb.toString();

        } catch (Throwable t) {
            if (telnet != null) {
                telnet.setIsValid(false);
            }
            t.printStackTrace();
            retVal = t.toString();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                }
            }
            if (be != null) {
                try {
                    be.close();
                } catch (Exception e) {
                }
            }
            try {
                //session在每次执行命令后都要关闭
                if (session != null) {
                    session.close();
                }
                if (telnet != null) {
                    if ("false".equals(pool)) {
                        telnet.disconnect();
                    } else {
                        TelnetConnPool.getInstance().free(ip, telnet);
                    }
                }
            } catch (Exception e) {
                logger.error("Failed when free a ssh2Connection", e);
            }
        }
        return retVal;
    }

    public static void main(String[] args) {

    }
}
